#include "ThreadMonitor.h"
#include "MyException.h"
#include "Byte_Tiempo.h"
#include <fstream>
#include <ctime>
#include <dirent.h>

int tamanioArchivo(const char * nombre)
{
    FILE * fd = fopen(nombre,"rb");
    fseek(fd,0,SEEK_END);
    int tam = ftell(fd);
    fclose(fd);
    return tam;
}

size_t obtenerPesoDirectorio(const char * dirName){
	DIR *dir;
	struct dirent *ent;

	std::string path(USRDIR);
	path += dirName;
	dir = opendir(path.c_str());
	if (!dir) {throw MyException("No se ha encontrado el directorio a pollear");}

	size_t tam = 0;
	while ((ent = readdir(dir)) != NULL) {
		std::string pathFile(path);
		pathFile += "/";
		pathFile += ent->d_name;
		//std::cout << "el tamaño hasta el archivo " << pathFile << " es: " << tam << std::endl;
		if (ent->d_type == DT_REG) tam += tamanioArchivo(pathFile.c_str());
	}
	//std::cout << "el tamaño del directorio " << path << " es: " << tam << std::endl;
	return tam;
}

ThreadMonitor::ThreadMonitor(int p){
	port = p;
}

ThreadMonitor::~ThreadMonitor(){}

void ThreadMonitor::run(){
	try
	{
		unsigned int i = 0 ;
		// Inicializo el socket para aceptar conexiones.
		this->socket.setAddr_in(this->port, NULL);
		int retorno = this->socket.escucharPuerto(this->port);
		if (retorno != 0){throw MyException("No se puede listenear en puerto del monitor server");}
		while(this->running)
		{
			struct sockaddr_in clienteAux;
			int socketCliente = this->socket.aceptarCliente(clienteAux, sizeof(clienteAux));
			if (socketCliente == -1){throw MyException("No acepta mas conexiones");}
			bool AtendiendoCliente = true;
			Comunicador comunicador(socketCliente);
			time_t tiempoInicial = time(NULL);
			time_t tiempoActual = tiempoInicial;
			// Envia el tamaño del repo y el tiempo.
			while (AtendiendoCliente && this->running)
			{
				DIR *dir;
				struct dirent *ent;
				dir = opendir(USRDIR);
				if (!dir) {throw MyException("No se ha encontrado el directorio a pollear");}
				size_t tam = 0;
				while ((ent = readdir(dir)) != NULL) 
				{
					if (ent->d_type == DT_DIR)
					{
						if(strcmp(ent->d_name, ".") == 0) continue;
						if(strcmp(ent->d_name, "..") == 0) continue;
						tam += obtenerPesoDirectorio(ent->d_name);
					}
				}
				tiempoActual = time(NULL);
				double segundos = difftime(tiempoActual,tiempoInicial);
				Byte_Tiempo bt(int(segundos), tam);
				std::string buff(bt.Serializar());
				try
				{
					int ret = comunicador.enviarMensaje(buff);
					if ( ret == 0 ){ AtendiendoCliente = false;break; }
					std::string recm;
					ret = comunicador.recibirMensaje(recm);
					if ( recm == FIN ){AtendiendoCliente = false;break;}
					if ( ret == 0 ){AtendiendoCliente = false;break;}
					sleep(5);
				}
				catch(MyException& e)
				{
					std::cout << e.what() << std::endl;
					syslog(LOG_ERR,e.what());
				}
			}
		}
	syslog(LOG_INFO,"Se cerro thread monitor satisfactoriamente");
	}
	catch(MyException& e)
	{
		std::cout << e.what() << std::endl;
		syslog(LOG_ERR, e.what() );
	}
}

void ThreadMonitor::stop(){
	try
	{
		this->running = false;
		this->socket.cerrarSocket();
	}
	catch(MyException& e)
	{
		std::cout << e.what() << std::endl;
	}
}
